package com.ruoyi.caigou.service.impl;

import com.ruoyi.IndexDtoByTwo;
import com.ruoyi.activiti.api.RemoteActivitiService;
import com.ruoyi.caigou.mapper.BuyBackOrderDetailMapper;
import com.ruoyi.caigou.mapper.BuyBackOrderMapper;
import com.ruoyi.caigou.mapper.BuyBackReqMapper;
import com.ruoyi.caigou.service.IBuyBackOrderService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.finance.api.RemoteReciveReqService;
import com.ruoyi.store.api.RemoteWarehouseGoodsService;
import com.ruoyi.system.api.RemoteStockInDetailService;
import com.ruoyi.system.api.constants.BuyBackOrderConstants;
import com.ruoyi.system.api.domain.caigou.BuyBackOrder;
import com.ruoyi.system.api.domain.caigou.BuyBackOrderDetail;
import com.ruoyi.system.api.domain.caigou.BuyBackReq;
import com.ruoyi.system.api.domain.store.StockIn;
import com.ruoyi.system.api.domain.store.StockInDetail;
import com.ruoyi.system.api.domain.store.WarehouseGoods;
import com.ruoyi.system.api.dto.ActApprovalDTO;
import com.ruoyi.system.api.dto.WarehouseGoodsDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 采购退货单Service业务层处理
 *
 * @author wl
 * @date 2024-10-25
 */
@Service
@Slf4j
public class BuyBackOrderServiceImpl implements IBuyBackOrderService {
    @Autowired
    private BuyBackOrderMapper buyBackOrderMapper;

    @Autowired
    private BuyBackOrderDetailMapper buyBackOrderDetailMapper;

    @Autowired
    private BuyBackReqMapper buyBackReqMapper;

    @Autowired
    private RemoteStockInDetailService remoteStockInDetailService;

    @Autowired
    private RemoteActivitiService remoteActivitiService;

    @Autowired
    private RemoteReciveReqService remoteReciveReqService;

    @Autowired
    private RemoteWarehouseGoodsService remoteWarehouseGoodsService;

    /**
     * 查询采购退货单
     *
     * @param id 采购退货单主键
     * @return 采购退货单
     */
    @Override
    public AjaxResult selectBuyBackOrderById(Integer id) {
        BuyBackOrder buyBackOrder = buyBackOrderMapper.selectBuyBackOrderById(id);
        //获取采购退货详情
        List<BuyBackOrderDetail> buyBackOrderDetailList = buyBackOrderDetailMapper.selectBuyBackOrderDetailByBuyBackOrderId(buyBackOrder.getId());
        buyBackOrder.setBuyBackOrderDetailList(buyBackOrderDetailList);
        log.info("BuyBackOrderServiceImpl selectBuyBackOrderById buyBackOrder:{}", buyBackOrder);
        return AjaxResult.success(buyBackOrder);
    }

    @Override
    public IndexDtoByTwo getBuyBackCountAndMoney() {
        return buyBackOrderMapper.getBuyBackCountAndMoney();
    }

    /**
     * 查询采购退货单列表
     *
     * @param buyBackOrder 采购退货单
     * @return 采购退货单
     */
    @Override
    public List<BuyBackOrder> selectBuyBackOrderList(BuyBackOrder buyBackOrder) {

        return buyBackOrderMapper.selectBuyBackOrderList(buyBackOrder);
    }

    @Override
    public List<BuyBackOrder> noReconList(BuyBackOrder buyBackOrder) {

        return buyBackOrderMapper.noReconList(buyBackOrder);
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 添加采购退货单
     * @date 2024/11/7 下午1:46
     * @Param buyBackOrder:
     **/
    @Transactional
    public AjaxResult insertBuyBackOrder(BuyBackOrder buyBackOrder) {
        // 校验采购退货单编码
        AjaxResult validationResult = validateBuyBackOrder(buyBackOrder);
        if (validationResult != null) {
            return validationResult;
        }

        // 获取采购退货申请单对象及相关信息
        BuyBackReq buyBackReq = buyBackReqMapper.selectBuyBackReqById(buyBackOrder.getBuyBackReqId());
        StockIn stockIn = buyBackReq.getStockIn();
        R<List<StockInDetail>> stockInDetailListR = remoteStockInDetailService.getStockInDetailListByStockInId(stockIn.getId());
        List<StockInDetail> stockInDetailList = stockInDetailListR.getData();

        // 初始化采购退货单
        initializeBuyBackOrder(buyBackOrder);

        // 校验并计算退货详情
        AjaxResult detailValidationResult = validateAndCalculateDetails(buyBackOrder, stockInDetailList);
        if (detailValidationResult != null) {
            return detailValidationResult;
        }

        // 插入采购退货单并处理明细
        int addNum = insertBuyBackOrderDetails(buyBackOrder);

        log.info("BuyBackOrderServiceImpl insertBuyBackOrder buyBackOrder:{} addNum:{}", buyBackOrder, addNum);

        //采购退货申请添加审核任务
        ActApprovalDTO actApprovalDTO = new ActApprovalDTO();
        actApprovalDTO.setProcessDefinitionKey("buyBackOrderBPMN");
        actApprovalDTO.setOrderCode(buyBackOrder.getBuyBackOrderCode());
        actApprovalDTO.setTaskName(buyBackOrder.getBuyBackOrderCode() + "采购退货");
        actApprovalDTO.setDeptId(103);
        AjaxResult addApprovalAjaxResult = remoteActivitiService.addApproval(actApprovalDTO);
        Integer code = (Integer) addApprovalAjaxResult.get("code");
        if (code != 200) {
            throw new RuntimeException("新增失败");
        }
        return AjaxResult.success();
    }

    // 校验采购退货单的基本信息
    private AjaxResult validateBuyBackOrder(BuyBackOrder buyBackOrder) {
        if (StringUtils.isBlank(buyBackOrder.getBuyBackOrderCode())) {
            return AjaxResult.error("采购退货单编码不能为空");
        }
        if (buyBackOrderMapper.selectBuyBackOrderCodeCountByCode(buyBackOrder.getBuyBackOrderCode()) > 0) {
            return AjaxResult.error("采购退货单编码已存在");
        }
        if (buyBackOrder.getOrderDate() == null) {
            return AjaxResult.error("单据日期不能为空");
        }
        if (buyBackOrder.getSupplierId() == null) {
            return AjaxResult.error("供应商不能为空");
        }
        if (buyBackOrder.getBuyBackReqId() == null) {
            return AjaxResult.error("采购退货申请单id不能为空");
        }
        return null;
    }

    // 初始化采购退货单的默认状态
    private void initializeBuyBackOrder(BuyBackOrder buyBackOrder) {
        buyBackOrder.setStockStatus(BuyBackOrderConstants.STOCK_STATUS_NULL);
        buyBackOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_SUBMITTED);
        buyBackOrder.setPayStatus(BuyBackOrderConstants.PAY_STATUS_NULL);
        buyBackOrder.setApprovalResult(BuyBackOrderConstants.APPROVAL_NOT_APPROVED);
        buyBackOrder.setRealInPrice(BigDecimal.ZERO);
        buyBackOrder.setRealOutStock(0);
        buyBackOrder.setIsCancel(0);
        buyBackOrder.setIsDel(0);
        buyBackOrder.setIsEffect(0);
        buyBackOrder.setIsClose(0);
        buyBackOrder.setCreateBy(SecurityUtils.getUsername());
        buyBackOrder.setCreateDate(new Date());
    }

    // 校验退货详情并计算应出库数量、应收金额
    private AjaxResult validateAndCalculateDetails(BuyBackOrder buyBackOrder, List<StockInDetail> stockInDetailList) {
        List<BuyBackOrderDetail> buyBackOrderDetailList = buyBackOrder.getBuyBackOrderDetailList();
        if (buyBackOrderDetailList == null || buyBackOrderDetailList.isEmpty()) {
            return AjaxResult.error("采购退货详情不能为空");
        }

        int stockTotal = 0;
        BigDecimal payTotal = BigDecimal.ZERO;

        for (BuyBackOrderDetail buyBackOrderDetail : buyBackOrderDetailList) {
            // 校验每一项退货明细
            AjaxResult detailValidationResult = validateBuyBackOrderDetail(buyBackOrderDetail);
            if (detailValidationResult != null) {
                return detailValidationResult;
            }

            //获取仓库现存商品数量，校验采购退货数量小于仓库库存
            WarehouseGoodsDTO warehouseGoodsDTO = new WarehouseGoodsDTO();
            warehouseGoodsDTO.setGoodsId(buyBackOrderDetail.getGoodsId());
            warehouseGoodsDTO.setHouseId(buyBackOrderDetail.getHouseId());
            R<List<WarehouseGoods>> warehouseGoodsListR = remoteWarehouseGoodsService.getWarehouseGoodsList(warehouseGoodsDTO);
            List<WarehouseGoods> warehouseGoodsList = warehouseGoodsListR.getData();
            if (warehouseGoodsList == null || warehouseGoodsList.isEmpty()) {
                return AjaxResult.error("仓库不存在该商品");
            }
            WarehouseGoods warehouseGoods = warehouseGoodsList.get(0);
            if (buyBackOrderDetail.getOutStock() > warehouseGoods.getStock()) {
                return AjaxResult.error("退货数量不能大于仓库库存");
            }

            // 计算应收金额
            BigDecimal inPrice = calculateInPrice(buyBackOrderDetail, stockInDetailList);
            buyBackOrderDetail.setInPrice(inPrice);

            stockTotal += buyBackOrderDetail.getOutStock();
            payTotal = payTotal.add(inPrice);
        }

        buyBackOrder.setAllOutStock(stockTotal);
        buyBackOrder.setAllInPrice(payTotal);
        return null;
    }

    // 校验单个采购退货单明细
    private AjaxResult validateBuyBackOrderDetail(BuyBackOrderDetail buyBackOrderDetail) {
        if (buyBackOrderDetail.getGoodsId() == null) {
            return AjaxResult.error("入库单明细商品不能为空");
        }
        if (buyBackOrderDetail.getHouseId() == null) {
            return AjaxResult.error("入库单明细仓库不能为空");
        }
        if (buyBackOrderDetail.getOutStock() == null || buyBackOrderDetail.getOutStock() == 0) {
            return AjaxResult.error("应出库数量不能为空");
        }
        if (buyBackOrderDetail.getOutStock() < 0) {
            return AjaxResult.error("应出库数量不能小于0");
        }
        return null;
    }

    // 计算采购退货单明细的单价
    private BigDecimal calculateInPrice(BuyBackOrderDetail buyBackOrderDetail, List<StockInDetail> stockInDetailList) {
        for (StockInDetail stockInDetail : stockInDetailList) {
            if (stockInDetail.getGoodsId().equals(buyBackOrderDetail.getGoodsId())) {
                return stockInDetail.getCost().multiply(BigDecimal.valueOf(buyBackOrderDetail.getOutStock()));
            }
        }
        return BigDecimal.ZERO;
    }

    // 插入采购退货单明细并返回插入数量
    @Transactional
    public int insertBuyBackOrderDetails(BuyBackOrder buyBackOrder) {
        int num = 0;
        if (buyBackOrder.getId() == null) {
            num = buyBackOrderMapper.insertBuyBackOrder(buyBackOrder);
        } else {
            num = buyBackOrderMapper.updateBuyBackOrder(buyBackOrder);
        }
        List<BuyBackOrderDetail> buyBackOrderDetailList = buyBackOrder.getBuyBackOrderDetailList();

        for (BuyBackOrderDetail buyBackOrderDetail : buyBackOrderDetailList) {
            // 初始化明细的状态
            buyBackOrderDetail.setCreateBy(SecurityUtils.getUsername());
            buyBackOrderDetail.setCreateDate(new Date());
            buyBackOrderDetail.setIsDel(0);
            buyBackOrderDetail.setBuyBackOrderId(buyBackOrder.getId());
            num += buyBackOrderDetailMapper.insertBuyBackOrderDetail(buyBackOrderDetail);
        }
        return num;
    }


    /**
     * 修改采购退货单
     *
     * @param buyBackOrder 采购退货单
     * @return 结果
     */
    @Transactional
    public AjaxResult updateBuyBackOrder(BuyBackOrder buyBackOrder) {
        //校验采购退货单id
        if (buyBackOrder.getId() == null) {
            return AjaxResult.error("采购退货单id不能为空");
        }
        //校验单据状态
        if (buyBackOrder.getOrderStatus() > BuyBackOrderConstants.ORDER_STATUS_SUBMITTED) {
            return AjaxResult.error("只有未提交状态可以修改");
        }
        BuyBackReq buyBackReq = buyBackReqMapper.selectBuyBackReqById(buyBackOrder.getBuyBackReqId());
        StockIn stockIn = buyBackReq.getStockIn();
        R<List<StockInDetail>> stockInDetailListR = remoteStockInDetailService.getStockInDetailListByStockInId(stockIn.getId());
        List<StockInDetail> stockInDetailList = stockInDetailListR.getData();

        // 校验并计算退货详情
        AjaxResult detailValidationResult = validateAndCalculateDetails(buyBackOrder, stockInDetailList);
        if (detailValidationResult != null) {
            return detailValidationResult;
        }
        //删除采购退货单原先的采购退货详情
        int delNum = buyBackOrderDetailMapper.deleteBuyBackOrderDetailByBuyBackOrderId(buyBackOrder.getId());
        log.info("BuyBackOrderServiceImpl updateBuyBackOrder deleteBuyBackOrderDetailByBuyBackOrderId buyBackOrderId:{} delNum:{}", buyBackOrder.getId(), delNum);

        //设置修改人 修改时间
        buyBackOrder.setModifyBy(SecurityUtils.getUsername());
        buyBackOrder.setModifyDate(new Date());
        // 插入采购退货单并处理明细
        int updNum = insertBuyBackOrderDetails(buyBackOrder);

        log.info("BuyBackOrderServiceImpl insertBuyBackOrder buyBackOrder:{} updNum:{}", buyBackOrder, updNum);

        if (updNum >= 1) {
            return AjaxResult.success();
        }
        return AjaxResult.error("修改失败");
    }

    /**
     * 批量删除采购退货单
     *
     * @param ids 需要删除的采购退货单主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteBuyBackOrderByIds(Integer[] ids) {
        //采购退货驳回的可以删除
        if (ids == null || ids.length == 0) {
            return AjaxResult.error("无效的ID数组");
        }
        List<BuyBackOrder> buyBackOrderList = buyBackOrderMapper.selectBuyBackOrderByIds(ids);
        for (BuyBackOrder buyBackOrder : buyBackOrderList) {
            if (buyBackOrder.getApprovalResult() != BuyBackOrderConstants.APPROVAL_REJECTED) {
                return AjaxResult.error("只有驳回状态可以删除");
            }
        }
        int delNum = buyBackOrderMapper.deleteBuyBackOrderByIds(ids);
        log.info("deleteBuyBackOrderByIds ids:{}", Arrays.toString(ids));
        if (delNum >= ids.length) {
            return AjaxResult.success();
        }
        return AjaxResult.error("删除失败");
    }

    /**
     * 删除采购退货单信息
     *
     * @param id 采购退货单主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteBuyBackOrderById(Integer id) {
        //采购退货驳回的可以删除
        if (id == null) {
            return AjaxResult.error("无效的ID");
        }
        BuyBackOrder buyBackOrder = buyBackOrderMapper.selectBuyBackOrderById(id);
        if (buyBackOrder.getApprovalResult() != BuyBackOrderConstants.APPROVAL_REJECTED) {
            return AjaxResult.error("只有驳回状态可以删除");
        }
        int delNum = buyBackOrderMapper.deleteBuyBackOrderById(id);
        log.info("deleteBuyBackOrderById id:{}", id);
        if (delNum > 0) {
            return AjaxResult.success();
        }
        return AjaxResult.error("删除失败");
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 审核后修改采购退货单状态
     * @date 2024/11/7 下午1:46
     * @Param buyBackOrder:
     **/
    public AjaxResult updateBuyBackOrderStatus(BuyBackOrder buyBackOrder) {
        if (buyBackOrder.getApprovalResult() == 2) {
            buyBackOrder.setEffectDate(new Date());
            buyBackOrder.setIsEffect(1);
            buyBackOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_APPROVED);
            buyBackOrder.setStockStatus(BuyBackOrderConstants.STOCK_STATUS_WAIT);
            buyBackOrder.setPayStatus(BuyBackOrderConstants.PAY_STATUS_WAIT);
        } else if (buyBackOrder.getApprovalResult() == 3) {
            buyBackOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_EXECUTED);
        }
        buyBackOrder.setModifyBy(SecurityUtils.getUsername());
        buyBackOrder.setModifyDate(new Date());
        buyBackOrder.setApprovalId(Math.toIntExact(SecurityUtils.getUserId()));

        int updNum = buyBackOrderMapper.updateBuyBackOrderByOrderCode(buyBackOrder);
        log.info("updateBuyBackOrderStatus buyBackOrder:{} updNum:{}", buyBackOrder, updNum);

        return AjaxResult.success();
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 根据采购退货编码获取详情
     * @date 2024/11/7 下午2:36
     * @Param buyBackOrderCode:
     **/
    public BuyBackOrder selectBuyBackOrderByBuyBackOrderCode(String buyBackOrderCode) {
        BuyBackOrder buyBackOrder = buyBackOrderMapper.selectBuyBackOrderByBuyBackOrderCode(buyBackOrderCode);
        //获取采购退货详情
        List<BuyBackOrderDetail> buyBackOrderDetailList = buyBackOrderDetailMapper.selectBuyBackOrderDetailByBuyBackOrderId(buyBackOrder.getId());
        buyBackOrder.setBuyBackOrderDetailList(buyBackOrderDetailList);
        return buyBackOrder;
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 修改采购退货详情
     * @date 2024/11/9 上午10:29
     * @Param buyBackOrderDetail:
     **/
    public AjaxResult updateBuyBackOrderDetail(BuyBackOrderDetail buyBackOrderDetail) {
        if (buyBackOrderDetail.getId() == null) {
            return AjaxResult.error("采购退货详情id不能为空");
        }
        int updNum = buyBackOrderDetailMapper.updateBuyBackOrderDetail(buyBackOrderDetail);
        log.info("updateBuyBackOrderDetail buyBackOrderDetail:{} updNum:{}", buyBackOrderDetail, updNum);
        if (updNum > 0) {
            return AjaxResult.success();
        }
        return AjaxResult.error("修改失败");
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 根据采购退货单id和商品id修改采购退货详情
     * @date 2024/11/11 下午2:12
     * @Param buyBackOrderDetail:
     **/
    public AjaxResult updateBuyBackOrderDetailByOrderIdGoodsId(BuyBackOrderDetail buyBackOrderDetail) {
        int updNum = buyBackOrderDetailMapper.updateBuyBackOrderDetailByOrderIdGoodsId(buyBackOrderDetail);
        log.info("updateBuyBackOrderDetailByOrderIdGoodsId buyBackOrderDetail:{} updNum:{}", buyBackOrderDetail, updNum);
        if (updNum > 0) {
            return AjaxResult.success();
        }
        return AjaxResult.error("修改失败");
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 财务收款单审核通过后修改状态
     * @date 2024/11/12 上午11:29
     * @Param buyBackOrder:
     **/
    public AjaxResult updateAfterAuditReciveOrder(BuyBackOrder buyBackOrder) {
        int updNum = buyBackOrderMapper.updateBuyBackOrder(buyBackOrder);
        log.info("updateAfterAuditReciveOrder buyBackOrder:{} updNum:{}", buyBackOrder, updNum);
        return AjaxResult.success();
    }

    /**
     * @return java.util.List<com.ruoyi.system.api.domain.caigou.BuyBackOrder>
     * @description 财务收款页面获取采购退货单列表
     * @date 2024/11/12 上午10:53
     * @Param buyBackOrder:
     **/
    public List<BuyBackOrder> selectBuyBackOrderListForReciveOrder(BuyBackOrder buyBackOrder) {
        List<BuyBackOrder> buyBackOrderList = buyBackOrderMapper.selectBuyBackOrderListForReciveOrder(buyBackOrder);
        return buyBackOrderList;
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 判断是否完成出库 完全收款
     * @date 2024/11/9 上午10:50
     * @Param id:
     **/
    public AjaxResult checkStockPayStatus(Integer id) {
        BuyBackOrder buyBackOrder = buyBackOrderMapper.selectBuyBackOrderById(id);
        if (buyBackOrder == null) {
            return AjaxResult.error("采购退货单不存在");
        }
        //判断是否完全出库 完全收款
        if (buyBackOrder.getPayStatus() == 3 && buyBackOrder.getStockStatus() == 3) {
            //关闭采购退货单
            buyBackOrder.setIsClose(1);
            // 采购退货单执行完
            buyBackOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_EXECUTED);
            int updNum = buyBackOrderMapper.updateBuyBackOrder(buyBackOrder);
            log.info("closeBuyBackOrder buyBackOrder:{} updNum:{}", buyBackOrder, updNum);
        }
        return AjaxResult.success();
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 根据采购退货单编号修改采购退货单
     * @date 2024/11/9 下午3:04
     * @Param buyBackOrder:
     **/
    public AjaxResult updateBuyBackOrderByOrderCode(BuyBackOrder buyBackOrder) {
        //校验采购退货单编号
        if (buyBackOrder.getBuyBackOrderCode() == null) {
            return AjaxResult.error("采购退货单编号不能为空");
        }
        //设置修改人 修改时间
        buyBackOrder.setModifyBy(SecurityUtils.getUsername());
        buyBackOrder.setModifyDate(new Date());
        // 插入采购退货单并处理明细
        int updNum = buyBackOrderMapper.updateBuyBackOrderByOrderCode(buyBackOrder);

        log.info("BuyBackOrderServiceImpl updateBuyBackOrderByOrderCode buyBackOrder:{} updNum:{}", buyBackOrder, updNum);

        if (updNum >= 1) {
            return AjaxResult.success();
        }
        return AjaxResult.error("修改失败");
    }

    /**
     * @return com.ruoyi.system.api.domain.caigou.BuyBackOrderDetail
     * @description 根据采购退货单id和商品id获取采购退货单详情
     * @date 2024/11/14 上午10:49
     * @Param buyBackOrderDetail:
     **/
    public BuyBackOrderDetail getBuyBackOrderDetailByOrderIdGoodsId(BuyBackOrderDetail buyBackOrderDetail) {
        return buyBackOrderDetailMapper.getBuyBackOrderDetailByOrderIdGoodsId(buyBackOrderDetail);
    }
}
